import React, { useState, useEffect, useId } from 'react';
import { useMemoizedFn } from 'ahooks';

let globalActiveId: string | undefined;
let globalCancelFunc: (() => void) | undefined;

function useRun<T extends Function>(runFunc: T, cancelFunc?: Function) {
  const componentId = useId();
  const [isRunning, setIsRunning] = useState(false);

  const cancelFuncRef = useMemoizedFn(() => {
    if (globalActiveId && globalActiveId === componentId) {
      globalActiveId = undefined;
      globalCancelFunc = undefined;
      setIsRunning(false);
      if (cancelFunc) cancelFunc();
    }
  });

  const runWithCancel = useMemoizedFn((...args) => {
    // 如果有之前运行中的
    if (globalActiveId && globalCancelFunc) {
      globalCancelFunc();
    }

    // 运行新的
    globalActiveId = componentId;
    globalCancelFunc = cancelFuncRef;
    setIsRunning(true);
    runFunc(...args);
  }) as any as T;

  const toggleRef = useMemoizedFn((...args) => {
    // 运行中，取消
    if (isRunning) {
      cancelFuncRef();
    }
    // 否则，运行
    else {
      runWithCancel(...args);
    }
  }) as any as T;

  useEffect(() => cancelFuncRef, [componentId, cancelFuncRef]);

  return { run: runWithCancel, toggle: toggleRef, cancel: cancelFuncRef, isRunning };
}

export function useStateRun<T>(initState?: T): ReturnType<typeof useState<T>> {
  const [state, setState] = useState<T | undefined>(initState);

  const { run, cancel } = useRun(setState, setState);

  const setStateRef = useMemoizedFn((newState?: T) => {
    if (newState === undefined || newState === state) cancel();
    else run(newState);
  });

  return [state, setStateRef];
}

export function useCancelRun(item: any) {
  useEffect(() => {
    if (item !== undefined && item !== null) {
      cancelRun();
    }
  }, [item]);
}

export const cancelRun = () => {
  globalCancelFunc && globalCancelFunc();
};

export default useRun;
